`timescale  1ns/1ps

module freequency_measure_tb();


reg  clk             ;
reg  rst_n           ;
reg  din             ;
reg  din2           ;
wire[31 : 0] cnt_fs_p    ; 
wire [31 : 0] cnt_fs_n   ;
wire [31 : 0] cnt_fx     ;
wire [31 : 0] cnt_fy     ;
reg gate;
wire valid;
initial begin
    clk<=1'b0;
    clk<=1'b0;
    #5 rst_n<=1'b1;
    #10 rst_n<=1'b0;
     din2<=1'b0;
     din <=1'b1;
    #15 rst_n<=1'b1;
    gate<=1'b0;
end
always #5 clk=~clk;
always #500_000 din2=~din2;
 always #500_000 din=~din;
always #10_000_000 gate=~gate;
    cymometer u_cymometer(.clk_fs(clk),.rst_n(rst_n),.clk_fx(din),.clk_fy(din2),.gate(gate),.u_cnt_fs_n(cnt_fs_n),.u_cnt_fs_p(cnt_fs_p),.u_cnt_fx(cnt_fx),.u_cnt_fy(cnt_fy));
endmodule




module cymometer #(
parameter  Counter_fs = 100_000_000,
parameter  Counter_fx = 100_000_000
)
(
    input  wire clk_fs          ,
    input  wire rst_n           ,
    input  wire clk_fx          ,
    input  wire clk_fy          ,
    input  wire gate            ,
    output reg valid            ,
    output reg [31 : 0] u_cnt_fs_p   , 
    output reg [31 : 0] u_cnt_fs_n   ,
    output reg [31 : 0] u_cnt_fx     ,
    output reg [31 : 0] u_cnt_fy      

);

    reg[31 : 0]  cnt_fs_p;
    reg [31 : 0] cnt_fs_n;
    reg [31 : 0] cnt_fx;  
    reg [31 : 0] cnt_fy;   
    reg     gate_out;
    reg     gate_out_d1;
    reg     gate_out_d2;
   // wire    valid;
   // reg     start;
    wire    negedge_gate_out;
    wire    posedge_gate_out;
    wire    cnt_fy_en;
   // reg [63:0] quotient;
    assign negedge_gate_out = gate_out_d2&(!gate_out_d1);
    assign posedge_gate_out = (!gate_out_d2)&(gate_out_d1);
    assign cnt_fy_en =((!clk_fx)&clk_fy)|((!clk_fy)&clk_fx);
//将GATE信号与FX同�?�，以保证GATE为整数个FX周期
    always @(posedge clk_fx or negedge rst_n)
    begin
        if(!rst_n)
            gate_out<=1'b0;
        else
            gate_out<=gate;
    end

    always @(posedge clk_fs or posedge gate_out)
    begin
        if(posedge_gate_out)
        begin
            cnt_fy<=32'd2;
        end else
        begin
            if(cnt_fy_en)
                cnt_fy<=cnt_fy+1;
        end
    end

    always @(posedge clk_fs or negedge rst_n)
    begin
        if(!rst_n)
        begin
            gate_out_d1<=1'b0;
            gate_out_d2<=1'b0;
        end else
        begin
            gate_out_d2<=gate_out_d1;
            gate_out_d1<=gate_out;
        end
    end

    always @(posedge clk_fs or negedge rst_n )
    begin
        if(!rst_n)
        begin
            cnt_fs_p<=32'b0;
            cnt_fs_n<=32'b0;
        end else
        begin
            if(gate_out)
            begin
                if (posedge_gate_out) 
                begin
                    cnt_fs_p<=32'd2;
                    cnt_fs_n<=32'b0;
                end else
                if(clk_fx)
                    cnt_fs_p<=cnt_fs_p+1'b1;
                else 
                    cnt_fs_n<=cnt_fs_n+1'b1;
            end
        end
    end

    always @(posedge clk_fx or posedge posedge_gate_out)
    begin
        if(posedge_gate_out)
            cnt_fx<=1'b0;
        else
        if(clk_fx)
            if(gate_out)
                cnt_fx<=cnt_fx+1'b1;
    end

    
    always @(posedge clk_fs or negedge rst_n) 
    begin
        if (!rst_n) begin
            valid<=1'b0;
            u_cnt_fs_p<=32'b0;
            u_cnt_fs_n<=32'b0;
            u_cnt_fx<=32'b0;
            u_cnt_fy<=32'b0;
        end else
        begin
        if(negedge_gate_out)
        begin
            valid<=1'b1;
            u_cnt_fs_p<=cnt_fs_p;
            u_cnt_fs_n<=cnt_fs_n;
            u_cnt_fx<=cnt_fx;
            u_cnt_fy<=cnt_fy;
        end
        else
            valid<=1'b0;
        end
    end
    //SlowDiv #(64)u_SlowDiv(.clk(clk_fs),.rst(!rst_n),.dividend(dividend),.divisor(divisor),.start(start),.quotient(quotient),.remainder(),.valid(valid),.busy());
endmodule

/*
module SlowDiv #( parameter W = 16 )(
    input wire clk, rst,
    input wire [W - 1 : 0] dividend,
    input wire [W - 1 : 0] divisor,
    input wire start,
    output logic [W - 1 : 0] quotient,
    output logic [W - 1 : 0] remainder,
    output logic valid, busy
);
    logic [W - 1 : 0] ddend, quot;
    logic [W * 2 - 2 : 0] dsor;
    logic bit_co;
    logic [$clog2(W)-1 : 0] bit_cnt;
    Counter #(W) cntBit(clk, !(rst | start & ~busy), busy, bit_cnt, bit_co);
    always_ff@(posedge clk) begin
        if(rst) busy <= '0;
        else if(bit_co) busy <= '0;
        else if(start) busy <= '1;
    end
    always_ff@(posedge clk) begin
        if(busy) begin
            dsor <= dsor >> 1;
            if(ddend >= dsor) begin
                ddend <= ddend - dsor;
                quot <= (quot << 1) | 1'b1;
            end
            else quot <= quot << 1;
        end
        else if(start) begin
            ddend <= dividend;
            dsor <= {divisor, (W-1)'(0)};
            quot <= '0;
        end
    end
    always_ff@(posedge clk) begin
        if(bit_co) begin
            if(ddend >= dsor) begin
                remainder <= ddend - dsor;
                quotient <= (quot << 1) | 1'b1;
            end
            else begin
                remainder <= ddend;
                quotient <= quot << 1;
            end
        end
    end
    always_ff@(posedge clk) valid <= bit_co;
endmodule
*/
module Counter #(
    parameter M = 100
)(
    input wire clk, rst_n, en,
    output reg [$clog2(M) - 1 : 0] cnt,
    output wire co
);
    assign co = en & (cnt == M - 1);
    always@(posedge clk) begin
        if(!rst_n) cnt <= 1'b0;
        else if(en) begin
            if(cnt < M - 1) cnt <= cnt + 1'b1;
            else cnt <= 1'b0;
        end
    end
endmodule